package com.dbq.fast.util;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.IntEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.FloatRange;
import android.support.annotation.IdRes;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.annotation.StyleRes;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.dbq.fast.App;
import com.dbq.fast.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by Administrator on 2016/7/4.
 */
public class WindowToast implements View.OnTouchListener {

    private static final int TOUCH_Y = -8;
    private static WindowToast result;
    public final Context mContext;
    private static View sView;

    public WindowManager mWManager;
    public WindowManager.LayoutParams mParams;
    public static boolean canDrawOverlays = true;
    private final Handler mHandler = new Handler();
    private final Runnable mShow = new Runnable() {
        @Override
        public void run() {
            handleShow();
        }
    };

    private final Runnable mHide = new Runnable() {
        @Override
        public void run() {
            handleHide();
        }
    };
    /**
     * @by zhiqiang 2016/7/4 width height的2个值
     */
    private static final int MATCH_PARENT = WindowManager.LayoutParams.MATCH_PARENT;
    private static final int WRAP_CONTENT = WindowManager.LayoutParams.WRAP_CONTENT;

    /**
     * @by zhiqiang 2016/7/4 Format的值
     */
    private static final int RGBA_8888 = PixelFormat.RGBA_8888;
    private static final int RGB_888 = PixelFormat.RGB_888;
    private static final int RGB_565 = PixelFormat.RGB_565;
    private static final int TRANSPARENT = PixelFormat.TRANSPARENT;
    private static final int OPAQUE = PixelFormat.OPAQUE;
    /**
     * @by zhiqiang 2016/7/5 显示的时长
     */
    public static final int SHORT_TIME = 2000;
    public static final int LONG_TIME = 3500;

    private static boolean isShow;//判断是否显示在界面上
    private CharSequence charSequence;

    @IntDef({RGBA_8888, RGB_888, RGB_565, TRANSPARENT, OPAQUE,})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Format {
    }

    public enum Mode {
        NOTIFY,//@by zhiqiang: 2016/7/4 通知模式
        AD, //@by zhiqiang: 2016/7/4 广告模式
        DIALOG,//@by zhiqiang: 2016/7/4 对话框模式
        CUSTOM,//@by zhiqiang: 2016/7/4 自定义模式
    }

    private Mode mMode = Mode.NOTIFY;//@by zhiqiang: 2016/7/4 默认通知模式

    private WindowToast(Context context) {
        mContext = context;
        mWManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        mParams = new WindowManager.LayoutParams();
        setMode(mMode);
    }

    public static WindowToast getInstance(Context context) {
        if (result == null) {
            synchronized (WindowToast.class) {
                if (result == null) {
                    result = new WindowToast(context);
                }
            }
        }
        return result;
    }

    /**
     * @by zhiqiang 2016/7/4 获取windowToast对象
     */
    public static WindowToast makeWindowToast(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (Settings.canDrawOverlays(context)) {
                canDrawOverlays = true;
            } else {
                canDrawOverlays = false;
            }
        }
        context = context.getApplicationContext();
        result = getInstance(context);
        if (sView == null) {
            sView = LayoutInflater.from(context).inflate(R.layout.window_toast, null);
        }
        sView.setOnTouchListener(result);
        return result;
    }

    public static WindowToast makeWindowToast(Context context, int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (Settings.canDrawOverlays(context)) {
                canDrawOverlays = true;
            } else {
                canDrawOverlays = false;
            }
        }
        context = context.getApplicationContext();
        result = getInstance(context);
        if (sView == null) {
            sView = LayoutInflater.from(context).inflate(R.layout.window_toast, null);
        }
        sView.findViewById(R.id.root).setBackgroundColor(context.getResources().getColor(color));
        sView.setOnTouchListener(result);
        return result;
    }

//    public static WindowToast makeWindowToast(Context context, @LayoutRes int layout) {
//        context = context.getApplicationContext();
//        result = getInstance(context);
//        if (sView == null) {
//            sView = LayoutInflater.from(context).inflate(layout, null);
//        }
//        sView.setOnTouchListener(result);
//        return result;
//    }

    public static WindowToast makeWindowToast(Context context, @NonNull View view) {
        result = getInstance(context);
        context = context.getApplicationContext();
        if (sView == null) {
            sView = view;
        }
        sView.setOnTouchListener(result);
        return result;
    }

    int downX;
    int direction;
    int downY;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getRawX();
                downY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                //@by zhiqiang: 2016/7/8
                int moveY = (int) event.getRawY() - downY;
                if (moveY < TOUCH_Y) {
                    handleHide();
                }
                //处于滑动状态就取消自动消失
                //  mHandler.removeCallbacks(mHide);
                int moveX = (int) event.getRawX() - downX;
                //判断滑动方向
                if (moveX > 0) {
                    direction = 1;
                } else {
                    direction = 2;
                }
                //   updateWindowLocation(moveX, mParams.y);
                break;
            case MotionEvent.ACTION_UP:
                if (Math.abs(mParams.x) > App.SCREEN_WIDTH / 2) {
                    //  startDismissAnimator(direction);
                } else {
                    // startRestoreAnimator();
                }
                break;
        }
        return true;
    }

    public void updateWindowLocation(int x, int y) {
        mParams.x = x;
        mParams.y = y;
        mWManager.updateViewLayout(sView, mParams);

    }

    private boolean isShowing = false;
    private ValueAnimator restoreAnimator = null;
    private ValueAnimator dismissAnimator = null;


    private void startRestoreAnimator() {
        restoreAnimator = ValueAnimator.ofInt(mParams.x, 0);
        restoreAnimator.setDuration(300);
        restoreAnimator.setEvaluator(new IntEvaluator());

        restoreAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                System.out.println("onAnimationUpdate:" + animation.getAnimatedValue());
                updateWindowLocation((Integer) animation.getAnimatedValue(), -getStatusBarHeight());
            }
        });
        restoreAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                restoreAnimator = null;
                //autoDismiss();
            }
        });
        restoreAnimator.start();
    }

    private void startDismissAnimator(int direction) {
        if (direction == 2)
            dismissAnimator = ValueAnimator.ofInt(mParams.x, -App.SCREEN_WIDTH);
        else {
            dismissAnimator = ValueAnimator.ofInt(mParams.x, App.SCREEN_WIDTH);
        }
        dismissAnimator.setDuration(300);
        dismissAnimator.setEvaluator(new IntEvaluator());

        dismissAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                updateWindowLocation((Integer) animation.getAnimatedValue(), -getStatusBarHeight());
            }
        });
        dismissAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                restoreAnimator = null;
            }
        });
        dismissAnimator.start();
    }


    /**
     * @by zhiqiang 2016/7/4 给window设置模式
     */
    public void setMode(Mode mode) {
        switch (mode) {
            case NOTIFY:
                setNotifyParams();
                break;
            case AD:
                setAdParams();
                break;
            case DIALOG:
                setDialogParams();
                break;
            case CUSTOM:

                break;
            default:
                setNotifyParams();
                break;
        }
    }

    /**
     * @by zhiqiang 2016/7/4  通知模式
     */
    private void setNotifyParams() {
        setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);// flags设置没有交点|设置突破手机屏幕尺寸的限制
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (Settings.canDrawOverlays(mContext)) {
                canDrawOverlays = true;
                setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
            }else{
                canDrawOverlays = false;
            }

        } else {
            setType(WindowManager.LayoutParams.TYPE_TOAST);
        }
        setAlpha(1.0f);
        setFormat(RGBA_8888);
        setWidth(MATCH_PARENT);
        setHeight(WRAP_CONTENT);
        setGravity(Gravity.START | Gravity.TOP);
        setX(0);
        setY(-getStatusBarHeight());
        setAnimation(R.style.NotificationAnim);
    }

    /**
     * @by zhiqiang 2016/7/4 广告模式
     */
    private void setAdParams() {

    }

    /**
     * @by zhiqiang 2016/7/4 对话框模式
     */
    private void setDialogParams() {

    }

    public void show() {
        if(canDrawOverlays){
            if(FitBottomNavUtil.getAppOps(mContext)){
                mHandler.post(mShow);
            }else {
                Toast.makeText(mContext,charSequence,Toast.LENGTH_SHORT).show();
            }
        }else{
            Toast.makeText(mContext,charSequence,Toast.LENGTH_SHORT).show();
        }
    }

    public void show(int duration) {
        show();
        mHandler.removeCallbacks(mHide);
        mHandler.postDelayed(mHide, duration);
    }

    public void cancle() {
        mHandler.post(mHide);
    }

    private void handleShow() {
        if (sView != null) {
            if (sView.getParent() == null) {
                mWManager.addView(sView, mParams);
                isShow = true;
            }
        }
    }

    private void handleHide() {
        if (sView != null) {
            if (sView.getParent() != null) {
                mWManager.removeView(sView);
                isShow = false;
            }
            sView = null;
        }
    }

    public static boolean isShow() {
        return isShow;
    }

    private int getStatusBarHeight() {
        int height = 0;
        int resId = mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            height = mContext.getResources().getDimensionPixelSize(resId);
        }
        return height;
    }

    /**
     * @by zhiqiang 2016/7/4 通过id获取子控件
     */

    public <T extends View> T getChildView(@IdRes int id) {
        if (sView == null) return null;
        View view = sView.findViewById(id);
        return (T) view;
    }

    public WindowToast setPadding(int left, int top, int right, int bottom) {
        View view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setPadding(left, top, right, bottom);
        }
        return result;
    }

    /**
     * @by zhiqiang 2016/7/4 给相应的子控件设置属性
     */
    public WindowToast setVisiable(int visibility) {
        View view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setVisibility(visibility);
        }
        return result;
    }

    public WindowToast setVisiable(@IdRes int id, int visibility) {
        View view = getChildView(id);
        if (view != null) {
            view.setVisibility(visibility);
        }
        return result;
    }

    public WindowToast setBackgroundColor(@IdRes int id, @ColorInt int color) {
        View view = getChildView(id);
        if (view != null) {
            view.setBackgroundColor(color);
        }
        return result;
    }

    public WindowToast setBackgroundResource(@IdRes int id, @DrawableRes int resId) {
        View view = getChildView(id);
        if (view != null) {
            view.setBackgroundResource(resId);
        }
        return result;
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public WindowToast setBackground(@IdRes int id, @SuppressLint("SupportAnnotationUsage") @ColorInt Drawable drawable) {
        View view = getChildView(id);
        if (view != null) {
            view.setBackground(drawable);
        }
        return result;
    }

    public WindowToast setText(@NonNull CharSequence charSequence) {
        this.charSequence = charSequence;
        TextView view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setText(charSequence);
        }
        return result;
    }

    public WindowToast setText(@StringRes int string) {
        TextView view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setText(mContext.getString(string));
        }
        return result;
    }

    public WindowToast setText(@IdRes int id, @NonNull CharSequence charSequence) {
        TextView view = getChildView(id);
        if (view != null) {
            view.setText(charSequence);
        }
        return result;
    }

    public WindowToast setText(@IdRes int id, @StringRes int string) {
        TextView view = getChildView(id);
        if (view != null) {
            view.setText(mContext.getString(string));
        }
        return result;
    }

    public WindowToast setTextColor(@ColorInt int color) {
        TextView view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setTextColor(color);
        }
        return result;
    }

    public WindowToast setTextColor(@IdRes int id, @ColorInt int color) {
        TextView view = getChildView(id);
        if (view != null) {
            view.setTextColor(color);
        }
        return result;
    }

    public WindowToast setImageResource(@IdRes int id, @DrawableRes int resId) {
        ImageView view = getChildView(id);
        if (view != null) {
            view.setImageResource(resId);
        }
        return result;
    }

    public WindowToast setImageBitmap(@IdRes int id, Bitmap bitmap) {
        ImageView view = getChildView(id);
        if (view != null) {
            view.setImageBitmap(bitmap);
        }
        return result;
    }

    /**
     * @by zhiqiang 2016/7/4 设置params的方法
     */
    public void setWidth(int width) {
        mParams.width = width;
    }

    public void setHeight(int height) {
        mParams.height = height;
    }

    public void setX(int x) {
        mParams.x = x;
    }

    public void setY(int y) {
        mParams.y = y;
    }

    public void setFlags(int flags) {
        mParams.flags = flags;
    }

    public void setType(int type) {
        mParams.type = type;
    }

    public void setGravity(int gravity) {
        mParams.gravity = gravity;
    }

    public void setFormat(@Format int format) {
        mParams.format = format;
    }

    public void setAnimation(@StyleRes int style) {
        mParams.windowAnimations = style;
    }


    public void setAlpha(@FloatRange(from = 0.0f, to = 1.0f) float alpha) {
        mParams.alpha = alpha;
    }
}
